home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Science⁄Math / VideoToolbox / VideoToolboxSources / MakeNoise.c < prev    next >
Text File  |  1993-03-04  |  7KB  |  159 lines

  1. /* MakeNoise.c
  2. © 1989-1992 Denis G. Pelli.
  3. MakeNoise1() fills a PixMap with noise. The noise is made up of black & white cells,
  4. each dx pixels wide by dy pixels high. Random phase is optional.
  5.  
  6. If your PixMap baseAddr==NULL then the data area will be allocated for you.
  7. In that case you must set frame.bounds and frame.pixelSize. Everything else will be
  8. filled in by MakeNoise1. It will install a handle to the current device's color table.
  9. The values filled into the fields are necessarily somewhat arbitrary. For more
  10. control, fill in the fields yourself, using NewPixMap(), and allocate the data area
  11. yourself before calling MakeNoise1.
  12.  
  13. I suggest that new programs use MakeNoise1(). The old MakeNoise() is retained
  14. only for the sake of old programs.
  15.  
  16. MakeNoise() fills an array of PixMaps with noise, by calling MakeNoise1()
  17. repeatedly. However, it first sets the baseAddr to zero, so each data area
  18. will always be allocated, for compatibility with old programs. 
  19. You must set movie[0].bounds and movie[0].pixelSize to the desired values,
  20. the rest of the parameters (and all the rest of the PixMaps) will be set up for you.
  21. If memory runs out before all the PixMap data areas are allocated then
  22. *maxFramesPtr is reduced accordingly.
  23.  
  24. MakeNoise1 uses the current ForeColor and BackColor to make the noise, so
  25. make sure you've set the port to something appropriate. (And, if baseAddr==NULL,
  26. it shares the color table of the current device, so the device should be 
  27. reasonable too.) Apple's GetGWorld and SetGWorld calls are a convenient way of
  28. getting, changing, and restoring the port and device.
  29.  
  30. HISTORY:
  31. 6/21/89 dgp    changed frameBytes and bufferBytes to long so that this code won't crash
  32.             if the pixelSize is greater than 1 bit.
  33. 8/5/89 dgp    wrote and installed randU(), which yields two random bytes per call, instead
  34.             of rand() which yields only one, allowing the noise generation to go twice
  35.             as fast.
  36. 3/11/90 dgp    Changed dx and dy from int to double. This allows nonuniform cell size,
  37.             which arises when CopyBits expands by these nonintegral factors. Results
  38.             will be same as before when integral values are supplied.
  39.             Made the cosmetic change of replacing "unsigned long" by "size_t".
  40. 3/20/90    dgp    make compatible with MPW C.
  41. 3/31/90    dgp    set pmVersion to zero for compatibility with QD32
  42. 8/7/90    dgp    Now uses the current ForeColor and BackColor to make the noise.
  43.             For future compatibility, now zeroes the packType, etc. fields.
  44. 10/1/90    dgp    Cosmetic changes: replaced two OffsetRect calls by CenterRectInRect call.
  45. 11/16/90 dgp Added RANDOM_PHASE.
  46. 4/20/91    dgp    Added new MakeNoise1() that accepts a single PixMap, and allocates
  47.             its data area only if baseAddr==NULL, otherwise assuming that it already
  48.             exists. I rewrote MakeNoise() to simply call MakeNoise1() repeatedly.
  49.             MakeNoise() now seems obsolete, but is retained for compatibility with old
  50.             programs.
  51. 4/24/91    dgp    Fixed bug introduced into MakeNoise() on 4/20, which resulted in all the
  52.             PixMaps using the same buffer.
  53. 8/6/91    dgp    Replaced use of randU() by RandFill(), which is twice as fast.
  54. 8/24/91    dgp    Made compatible with THINK C 5.0.
  55. 4/17/92    dgp    Removed hidden assumption that frame->bounds.top and frame->bounds.left
  56.             were both zero. If they were negative MakeNoise1 would allocate too 
  57.             little space, and then overwrite memory and crash.
  58. 4/27/92    dgp    Initialize all remaining fields of the frame PixMap, and copy the current
  59.             device's color table handle.
  60. 10/22/92 dgp Check for error in CopyBits.
  61. */
  62. #include "VideoToolbox.h"
  63. #include <math.h>
  64.  
  65. void MakeNoise(double dx,double dy,PixMap movie[],short *maxFramesPtr)
  66. {
  67.     int i,error;
  68.     Boolean randomPhase=1;
  69.  
  70.     /*
  71.     Always allocate each frame's data area.
  72.     This is an old decision, which seems silly now, but too many programs
  73.     would break if I changed it, so it stays.
  74.     */
  75.     for (i=0;i<*maxFramesPtr;i++){
  76.         movie[i]=movie[0];
  77.         movie[i].baseAddr=NULL;
  78.         error=MakeNoise1(dx,dy,randomPhase,&movie[i]);
  79.         if(error)break;
  80.     }
  81.     *maxFramesPtr=i;
  82. }
  83.  
  84. Boolean MakeNoise1(double dx,double dy,Boolean randomPhase,PixMap *frame)
  85. {
  86.     BitMap buffer,bigBuffer;
  87.     Rect srcRect;
  88.     size_t frameBytes,bufferBytes;
  89.     RGBColor blackRGB={0,0,0},whiteRGB={0xffff,0xffff,0xffff},backRGB,foreRGB;
  90.     PixMap **pm;
  91.     OSErr error;
  92.     
  93.     GetBackColor(&backRGB);
  94.     GetForeColor(&foreRGB);
  95.     
  96.     srandU((unsigned int)rand());    /* seed my unsigned random number generator */
  97.  
  98.     /* allocate buffer BitMap */
  99.     SetRect(&buffer.bounds,0,0,1+(int)ceil((frame->bounds.right-frame->bounds.left)/dx),
  100.         1+(int)ceil((frame->bounds.bottom-frame->bounds.top)/dy));
  101.     buffer.rowBytes=(buffer.bounds.right + 31 & ~31)/8; /* round up to multiple of 32 bits */
  102.     bufferBytes=(size_t) buffer.rowBytes * (size_t) buffer.bounds.bottom;
  103.     buffer.baseAddr=(Ptr) NewPtr(bufferBytes);
  104.     if(buffer.baseAddr == NULL)
  105.         PrintfExit("\007MakeNoise1: sorry, not enough memory for buffer.\n");
  106.  
  107.     /* allocate bigBuffer BitMap */
  108.     SetRect (&bigBuffer.bounds,0,0,(int)floor(buffer.bounds.right*dx+0.5),
  109.         (int)floor(buffer.bounds.bottom*dy+0.5));
  110.     bigBuffer.rowBytes=(bigBuffer.bounds.right + 31 & ~31)/8; /* round up to multiple of 32 bits */
  111.     bigBuffer.baseAddr=(Ptr) NewPtr((size_t) bigBuffer.rowBytes * (size_t) bigBuffer.bounds.bottom);
  112.     if(bigBuffer.baseAddr == NULL){
  113.         PrintfExit("\007MakeNoise1: sorry, not enough memory for bigBuffer.\n");
  114.     }
  115.  
  116.     /* if necessary, fill in frame's fields and allocate its data area */
  117.     if(frame->baseAddr == NULL){
  118.         frame->hRes=frame->vRes=0x480000;    // 72 dpi
  119.         frame->pmVersion=frame->packType=frame->packSize=0;
  120.         frame->planeBytes=frame->pmReserved=0;
  121.         frame->cmpCount=1;
  122.         frame->cmpSize=frame->pixelSize;
  123.         frame->pmTable=(**(**GetGDevice()).gdPMap).pmTable;
  124.         frame->rowBytes=((frame->bounds.right-frame->bounds.left)*frame->pixelSize + 31 & ~31)/8; /* round up to multiple of 32 bits */
  125.         frameBytes=(size_t) frame->rowBytes * (frame->bounds.bottom-frame->bounds.top);
  126.         frame->rowBytes |= 0x8000;    /* Mark it as a PixMap */
  127.         frame->baseAddr=(char *) NewPtr(frameBytes);
  128.         if(frame->baseAddr == NULL)return 1;    /* error return */
  129.     }
  130.     if((size_t)frame->baseAddr%4 != 0L){
  131.         printf("Frame buffer address is not long aligned.\007\n");
  132.     }
  133.  
  134.     /* create random noise */
  135.     /* First create a random bit image, all bits uncorrelated. */
  136.     RandFill(buffer.baseAddr,bufferBytes);
  137.     /* Now expand image so that each random bit becomes a dx by dy rectangle. */
  138.     RGBBackColor(&whiteRGB);
  139.     RGBForeColor(&blackRGB);
  140.     CopyBits(&buffer,&bigBuffer,&buffer.bounds,&bigBuffer.bounds,srcCopy,NULL);
  141.     error=QDError();
  142.     if(error)printf("MakeNoise1:a: CopyBits error %d\n",error);
  143.     /* Finally copy it into the frame, trimming it down to the correct size. */
  144.     RGBBackColor(&backRGB);
  145.     RGBForeColor(&foreRGB);
  146.     srcRect=frame->bounds;
  147.     OffsetRect(&srcRect,-srcRect.left,-srcRect.top);
  148.     if(randomPhase) OffsetRect(&srcRect,nrand(dx),nrand(dy));
  149.     else CenterRectInRect(&srcRect,&bigBuffer.bounds);
  150.     CopyBits(&bigBuffer,(BitMap *)frame,&srcRect,&frame->bounds,srcCopy,NULL);
  151.     error=QDError();
  152.     if(error)printf("MakeNoise1:b: CopyBits error %d\n",error);
  153.     DisposPtr((void *) buffer.baseAddr);
  154.     DisposPtr((void *) bigBuffer.baseAddr);
  155.     return 0;
  156. }
  157.  
  158.  
  159.